﻿using FluentParser.Expressions;
using FluentParser.Expressions.Rules.Composition;
using FluentParser.Utils;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentParser.Tests.Expressions.Rules.Composition
{
    [TestClass]
    public class GroupSymbolRuleTests
    {
        [TestMethod]
        public void Parse_WhenTwoValidNodes_ShouldReturnTheTuple()
        {
            GroupSymbolRule symbol = new GroupSymbolRule("LeftToken", "RightToken");
            ParsingResult<object> result = symbol.Parse("LeftTokenRightTokenAndSomethingElse");

            var expected = Tuple.Create<object, object>("LeftToken", "RightToken");
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenSecondInvalid_ShouldReturnNull()
        {
            GroupSymbolRule symbol = new GroupSymbolRule("LeftToken", "RightToken");

            var expected = (ParsingResult<string>)null;
            var actual = symbol.Parse("LeftTokenAndSomethingElse");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenBothInvalid_ShouldReturnNull()
        {
            GroupSymbolRule symbol = new GroupSymbolRule("LeftToken", "RightToken");

            var expected = (ParsingResult<string>)null;
            var actual = symbol.Parse("LeftSomethingElse");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseNode_WhenTwoValidNodes_ShouldReturnTheTuple()
        {
            GroupSymbolRule symbol = new GroupSymbolRule("LeftToken", "RightToken");
            ParsingNodeResult node = symbol.ParseNode("LeftTokenRightTokenAndSomethingElse");

            string expected = "LeftTokenRightToken";
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            node.AssertLength(expected);
            node.AssertExploredLength(expected);

            node.AssertChildren(
                true, // LeftToken
                true); // RightToken
        }

        [TestMethod]
        public void ParseNode_WhenSecondInvalid_ShouldReturnNull()
        {
            GroupSymbolRule symbol = new GroupSymbolRule("LeftToken", "RightToken");
            ParsingNodeResult node = symbol.ParseNode("LeftTokenAndSomethingElse");

            string expected = null;
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            node.AssertLength("");
            node.AssertExploredLength("LeftToken?");

            node.AssertChildren(
                true, // LeftToken
                false); // RightToken
        }

        [TestMethod]
        public void ParseNode_WhenBothInvalid_ShouldReturnNull()
        {
            GroupSymbolRule symbol = new GroupSymbolRule("LeftToken", "RightToken");
            ParsingNodeResult node = symbol.ParseNode("LeftSomethingElse");

            string expected = null;
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            node.AssertLength("");
            node.AssertExploredLength("Left?");

            node.AssertChildren(
                false); // LeftToken
        }

    }
}